<?php
/**
 * Created by PhpStorm.
 * User: jjj
 * Date: 2017/8/11
 * Time: 16:17
 */

namespace app\common\model\teacher;


use app\admin\model\PageResponse;
use app\api\model\user\Users;
use app\common\lib\BaseModel;
use app\common\lib\rongcloud\RongCloud;
use app\common\model\ApiResponse;
use app\common\model\Chat;
use app\common\model\UserCreditRecord;
use think\Db;
use think\Model;

/**
 * Class Teacher
 * @package app\admin\model
 *
 * @property mixed id
 * @property mixed username
 * @property mixed password
 * @property mixed realname
 * @property mixed avatar
 * @property mixed gender
 * @property mixed intro
 * @property mixed success_rate
 * @property mixed num_followed
 * @property mixed chat_token
 * @property mixed degree_id
 * @property mixed rank
 * @property mixed hide
 * @property mixed recommend
 * @property mixed num_essay
 * @property mixed num_speaking
 * @property mixed num_curriculum_video
 * @property mixed qualification_certificate
 * @property mixed config
 */
class Teacher extends BaseModel
{
    protected $table = 'teacher';
    protected $pk = 'id';
    protected $field = [
        'id',
        'username',
        'password',
        'realname',
        'avatar',
        'gender',
        'intro',
        'success_rate',
        'num_followed',
        'chat_token',
        'degree_id',
        'rank',
        'hide',
        'recommend',
        'num_essay',
        'num_speaking',
        'num_curriculum_video',
        'qualification_certificate',
        'config',
        'list_img',
        'followed',
    ];
    const JSON_FIELDS = ['config'];

    const DEFAULT_AVATAR = '/static/img/default_avatar.png';

    public static function passwordEncrypt($passwordText) {
        return password_hash($passwordText, PASSWORD_DEFAULT);
    }
    public static function passwordVerify($passwordText, $passwordHash) {
        return password_verify($passwordText, $passwordHash);
    }

    /**
     * @param $username
     * @return null|static
     */
    public static function getByUserName($username) {
        return self::get(['username' => $username]);
    }

    /**
     * @return array
     */
    public function info() {
        return [
            'id' => $this->id,
            'username' => $this->username,
            'realname' => $this->realname,
            'avatar' => $this->avatar ? $this->avatar : self::DEFAULT_AVATAR,
            'gender' => $this->gender,
            'degree' => $this->getDegreeName(),
            'success_rate' => $this->success_rate,
            'intro' => $this->intro,
            'num_followed' => $this->num_followed,
            'num_essay' => $this->num_essay,
            'num_speaking' => $this->num_speaking,
            'num_curriculum_video' => $this->num_curriculum_video,
            'role' => 'admin',
            'roles' => ['admin'],
            'config' => $this->config,
        ];
    }

    public function getDegreeName() {
        $sql = 'select name from teacher_degree where id=:id';
        $re = Db::query($sql, ['id' => $this->degree_id]);
        return $re[0]['name'] ?? '';
    }


    /**
     * 获取聊天服务器的id和token
     *
     * @param $data
     * @return array|mixed
     */
    public static function chatToken($data) {

        if ($data instanceof Model) $data = $data->toArray();
        elseif ($data instanceof \stdClass) $data = (array)$data;

        $chatId = Chat::getChatId('t'.$data['id']);
        $chat = Chat::cache($chatId);
        if ($chat) {
            return $chat;
        }

        $rong = RongCloud::getInstance();
        $name = !empty($data['realname']) ? $data['realname'] : $data['username'];
        $avatar = !empty($data['avatar']) ? $data['avatar'] : Users::defaultAvatar();
        $re = $rong->User()->getToken($chatId, $name, $avatar);
        $chat_token = $re['token'];

        $chat = ['id' => $chatId, 'token' => $chat_token, 'avatar'=>$avatar, 'name' => $name,];
        Chat::cache($chatId, $chat);

        return $chat;
    }

    /**
     * 管理列表
     *
     * @param int $limit
     * @param int $offset
     * @param null $keywords
     * @return mixed
     */
    public static function manageList(int $limit, int $offset, $keywords = null) {

        $filter = $keywords ? " AND realname like :kw " : null;
        $params = ['limit' => $limit, 'offset' => $offset];

        if ($keywords) $params['kw'] = "%$keywords%";

        $sql = <<<SQL
SELECT * FROM teacher
WHERE TRUE {$filter}
ORDER BY id DESC 
LIMIT :limit OFFSET :offset
SQL;
        $list = Db::query($sql, $params);

        $sql = <<<SQL
SELECT count(id) as num FROM teacher
WHERE TRUE {$filter}
SQL;
        unset($params['limit'], $params['offset']);
        $re = Db::query($sql, $params);
        $total = $re[0]['num'] ?? 0;

        foreach ($list as & $item) {
            unset($item['password']);
            $item['config'] = json_decode($item['config']);
        }

        return PageResponse::success($list, $total);
    }

    /**
     * 简单列表，用于选择
     *
     * @return mixed
     */
    public static function listNames() {
        $sql = <<<SQL
SELECT id,username AS name,realname,avatar FROM teacher
SQL;
        $list = Db::query($sql);
        return $list;
    }

    public static function names4Api() {
        $sql = <<<SQL
SELECT id, realname AS name FROM teacher
SQL;
        return Db::query($sql);
    }

    /**
     * 检查用户名存在
     *
     * @param $username
     * @return bool
     */
    public static function checkUsername($username) {
        $sql = <<<SQL
SELECT exists( SELECT id FROM teacher WHERE username=:username LIMIT 1 ) e
SQL;
        $re = Db::query($sql, ['username' => $username]);
        return $re[0]['e'] ?? false;
    }

    /**
     *
     * @param $id
     * @param $hide
     */
    public static function setHide($id, $hide) {
        $sql = <<<SQL
UPDATE teacher SET hide = :hide WHERE id = :id
SQL;
        Db::query($sql, ['id' => $id, 'hide' => $hide]);
    }

    /**
     * 统计发表图文数
     *
     * @param $id
     */
    public static function countNumEssay($id) {
        $sql = <<<SQL
UPDATE teacher SET num_essay = (
SELECT count(*) FROM teacher_essay e WHERE e.teacher_id=teacher.id AND e.hide=FALSE 
) WHERE id=:id
SQL;
        Db::execute($sql, ['id' => $id,]);
    }

    /**
     * 统计发表语音数
     *
     * @param $id
     */
    public static function countNumSpeaking($id) {
        $sql = <<<SQL
UPDATE teacher SET num_speaking = (
SELECT count(*) FROM teacher_speaking e WHERE e.teacher_id=teacher.id
) WHERE id=:id
SQL;
        Db::execute($sql, ['id' => $id]);
    }

    /**
     * 统计视频数
     *
     * @param $id
     */
    public static function countNumVideo($id) {
        $sql = <<<SQL
UPDATE teacher SET num_curriculum_video = (
SELECT count(*) FROM curriculum_video e WHERE e.video_teacher=teacher.id AND e.hide=FALSE 
) WHERE id=:id
SQL;
        Db::execute($sql, ['id' => $id]);
    }



    /**
     * 随机获取几个
     *
     * @param int $limit
     * @return mixed
     */
    public static function rand(int $limit) {

        $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.success_rate,t.num_followed,t.followed,d.name AS degree
FROM teacher t
LEFT JOIN teacher_degree d ON t.degree_id=d.id
WHERE t.hide=FALSE 
ORDER BY t.rank ASC, t.id DESC 
LIMIT :limit
SQL;
        $list = Db::query($sql, ['limit'=>$limit]);

        foreach ($list as &$val) {
            $val['num_followed'] = countDataNum($val['num_followed'], $val['followed']);
            unset($val['followed']);
        }

        return $list;
    }

    /**
     * 推荐老师接口
     *
     * @param $num
     * @return mixed
     */
    public static function recommended($num, $uid=0) {
        $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.intro,t.success_rate,t.num_followed,t.followed,t.qualification_certificate,d.name AS degree
FROM teacher t
LEFT JOIN teacher_degree d ON t.degree_id=d.id
WHERE t.hide=FALSE AND t.recommend=TRUE 
ORDER BY t.rank ASC, t.id DESC 
LIMIT :num
SQL;
        $list = Db::query($sql, ['num' => intval($num)]);

        foreach ($list as &$val) {
            $is_follow = \app\api\model\Teacher::getFollowStatus($uid, $val['id']);
            $val['is_follow'] = $is_follow?true:false;
            // $val['num_followed'] = $val['num_followed']<$val['followed']?$val['followed']:$val['num_followed'];
            $val['num_followed'] = countDataNum($val['num_followed'], $val['followed']);
            unset($val['followed']);
        }

        return $list;
    }

    /**
     * API 列表
     *
     * @param int $limit
     * @param int $offset
     * @param int $uid
     * @param int $tag
     * @return mixed
     */
    public static function apiList(int $limit, int $offset, int $uid = 0, $tag = 0) {

        $params = ['limit'=>$limit, 'offset'=>$offset];
        if ($uid > 0) {
            $follow_query = ' exists( SELECT * FROM user_follow_teacher f WHERE f.teacher_id=t.id AND f.userid=:uid ) ';
            $params['uid'] = $uid;
        } else {
            $follow_query = ' false ';
        }

        if ($tag) {
            $tags_filter = ' AND t.id IN (select tt.teacher_id from teacher_tag tt where tt.tag_id=:tag_id)  ';
            $params['tag_id'] = $tag;
        } else {
            $tags_filter = null;
        }

        $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.intro,t.success_rate,t.num_followed,t.followed,t.num_essay,t.num_speaking,t.num_curriculum_video,
  d.name AS degree,
 {$follow_query} AS followed
FROM teacher t
LEFT JOIN teacher_degree d ON d.id=t.degree_id
WHERE t.hide=FALSE {$tags_filter}
ORDER BY t.rank asc,id DESC 
LIMIT :limit OFFSET :offset
SQL;
        $list = Db::query($sql, $params);

        foreach ($list as & $item) {
            $item['success_rate'] = ($item['success_rate'] * 100) . '%';

            $item['num_followed'] = $item['num_followed']<$item['followed']?$item['followed']:$item['num_followed'];
            unset($item['followed']);
        }

        return $list;
    }

    /**
     * @param int $tag
     * @return int
     */
    public static function apiTotal($tag = 0) {

        $params = [];
        if ($tag) {
            $tags_filter = ' AND t.id IN (select tt.teacher_id from teacher_tag tt where tt.tag_id=:tag_id)  ';
            $params['tag_id'] = $tag;
        } else {
            $tags_filter = null;
        }

        $sql = <<<SQL
SELECT count(*) total
FROM teacher t
LEFT JOIN teacher_degree d ON d.id=t.degree_id
WHERE t.hide=FALSE {$tags_filter}
SQL;

        $re = Db::query($sql, $params);

        return $re[0]['total'] ?? 0;
    }

    /**
     * API 详情
     *
     * @param int $teacher_id
     * @param int $uid
     * @return mixed|null
     */
    public static function apiDetail(int $teacher_id, int $uid = 0) {

        if ($uid > 0) {
            $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.gender,t.intro,t.num_followed,t.followed as set_followed,t.success_rate,d.name AS degree,
  exists(SELECT * FROM user_follow_teacher f WHERE f.teacher_id=t.id AND f.userid=:uid) AS followed
FROM teacher t
LEFT JOIN teacher_degree d ON d.id=t.degree_id
WHERE t.id=:teacher_id
SQL;
            $teacher = Db::query($sql, ['teacher_id' => $teacher_id, 'uid' => $uid]);
        } else {
            $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.gender,t.intro,t.num_followed,t.followed as set_followed,t.success_rate,d.name AS degree 
FROM teacher t 
LEFT JOIN teacher_degree d ON d.id=t.degree_id
WHERE t.id=:teacher_id
SQL;
            $teacher = Db::query($sql, ['teacher_id' => $teacher_id,]);
        }
        if (count($teacher) == 0) return null;

        $teacher = $teacher[0];
        $teacher['followed'] = $teacher['followed'] ?? false;
        $teacher['share_url'] = config('server.host') . '/static/AppShare/master.html';

        $teacher['num_followed'] = $teacher['num_followed']<$teacher['set_followed']?$teacher['set_followed']:$teacher['num_followed'];
        unset($teacher['set_followed']);

        return $teacher;
    }

    public static function detail(int $teacher_id, int $uid = 0) {
        $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.gender,t.intro,t.qualification_certificate,t.num_followed,t.followed,t.num_essay,t.num_speaking,t.num_curriculum_video,t.success_rate,d.name AS degree
FROM teacher t
LEFT JOIN teacher_degree d ON d.id=t.degree_id
WHERE t.id=:teacher_id
SQL;
        $teacher = Db::query($sql, ['teacher_id' => $teacher_id,]);
        if (count($teacher) == 0) return null;
        $teacher = $teacher[0];
        $teacher_id = $teacher['id'];

        $teacher['num_followed'] = $teacher['num_followed']<$teacher['followed']?$teacher['followed']:$teacher['num_followed'];
        unset($teacher['followed']);

        if ($uid > 0) {
            $sql = <<<SQL
SELECT exists(SELECT 1 FROM user_follow_teacher f WHERE f.teacher_id=:teacher_id AND f.userid=:uid) AS followed
SQL;
            $re = Db::query($sql, ['teacher_id'=>$teacher_id, 'uid' => $uid]);
            $teacher['followed'] = $re[0]['followed'] ?? false;
        } else {
            $teacher['followed'] = false;
        }

        // 老师tag
        $sql = 'SELECT t.title FROM tag t JOIN teacher_tag tt ON t.id = tt.tag_id WHERE tt.teacher_id=:teacher_id';
        $re = Db::query($sql, ['teacher_id' => $teacher_id]);
        $teacher['tags'] = array_column($re, 'title');


        $teacher['share_url'] = config('server.wapHost') . '/master/detail';

        return $teacher;
    }

    public static function checkFollow($teacher_id, $uid) {
        $sql = <<<SQL
SELECT exists(SELECT 1 FROM user_follow_teacher f WHERE f.teacher_id=:teacher_id AND f.userid=:uid) AS followed
SQL;
        $re = Db::query($sql, ['teacher_id'=>$teacher_id, 'uid' => $uid]);
        return $re[0]['followed'] ?? false;
    }

    /**
     * 加或取消关注
     *
     * @param int $teacher_id
     * @param int $userid
     * @param int $cancel
     * @return bool
     */
    public static function follow(int $teacher_id, int $userid, int $cancel) {

        try{
            Db::startTrans();

            if ($cancel) {
                $sql = 'delete from user_follow_teacher where teacher_id=:teacher_id AND userid=:userid';
            } else {
                $sql = 'insert into user_follow_teacher (userid, teacher_id) VALUES (:userid, :teacher_id) ON CONFLICT DO NOTHING ';
            }
            $n = Db::execute($sql, ['userid'=>$userid, 'teacher_id'=>$teacher_id]);
            if ($n > 0) {
                Db::execute(' update teacher set num_followed = num_followed + :inc WHERE id=:id',
                    ['id' => $teacher_id, 'inc' => ($cancel ? -1 : 1)]);
                if (!$cancel) {
                    Users::creditTask($userid, UserCreditRecord::CHANGE_TYPE_FOLLOWED_TEACHER, $teacher_id);
                }
            }

            Db::commit();

            return true;

        }catch (\Exception $ex) {
            Db::rollback();
            return false;
        }

    }

    /**
     * API 关注列表
     * @param int $uid
     * @param int $limit
     * @param int $offset
     * @param bool $pageTotal
     * @return mixed
     */
    public static function followedList(int $uid, int $limit, int $offset, $pageTotal = false) {

        $params = ['uid'=>$uid, 'limit'=>$limit, 'offset'=>$offset,];
        $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,
 d.name AS degree,
 (SELECT e.summary FROM teacher_essay e WHERE e.teacher_id=t.id AND e.hide=FALSE ORDER BY id DESC LIMIT 1) AS last_essay 
FROM teacher t JOIN user_follow_teacher f ON t.id = f.teacher_id
JOIN teacher_degree d ON d.id=t.degree_id
WHERE f.userid=:uid
ORDER BY t.rank ASC,t.id DESC 
LIMIT :limit OFFSET :offset
SQL;
        $list = Db::query($sql, $params);

        foreach ($list as & $item) {
            $item['last_essay'] = fetchTextFromHtml($item['last_essay']);
        }
        if (!$pageTotal) return $list;

        $sql = <<<SQL
SELECT count(*) total
FROM teacher t JOIN user_follow_teacher f ON t.id = f.teacher_id
JOIN teacher_degree d ON d.id=t.degree_id
WHERE f.userid=:uid
SQL;
        unset($params['limit'],$params['offset']);
        $re = Db::query($sql, $params);
        $total = $re[0]['total'] ?? 0;

        return ['list' => $list, 'total' => $total];
    }

    /**
     * recommendeds
     * 推荐老师接口
     *
     * @author zhengkai
     * @date 2018-04-23
     *
     * @param $num
     * @return mixed
     */
    public static function recommendeds($num) {
        $sql = <<<SQL
SELECT t.id,t.realname,t.avatar,t.intro,t.num_followed,t.followed,d.name AS degree
FROM teacher t
LEFT JOIN teacher_degree d ON t.degree_id=d.id
WHERE t.hide=FALSE AND t.recommend=TRUE 
ORDER BY t.rank ASC, t.id DESC 
LIMIT :num
SQL;
        $list = Db::query($sql, ['num' => intval($num)]);

        foreach ($list as &$val) {
            // 老师文章总数统计
            $articleCount = Db::table('teacher_essay')->where('teacher_id', $val['id'])->where('hide', 'false')->count();
            $val['article_total'] = $articleCount;

            // 老师课程视频总数统计
            $courseCount = Db::table('curriculum_video')->where('video_teacher', $val['id'])->where('hide', 'false')->count();
            $val['course_total'] = $courseCount;

            // 老师语音总数统计
            $audioCount = Db::table('teacher_speaking')->where('teacher_id', $val['id'])->count();
            $val['audio_total'] = $audioCount;

            // 老师问答总数统计
            $askCount = Db::table('ask')->where('ask_teacher', $val['id'])->count();
            $val['ask_total'] = $askCount;

            $val['num_followed'] = $val['num_followed']<$val['followed']?$val['followed']:$val['num_followed'];
            unset($val['followed']);
        }

        return $list;
    }
}